#pragma once

#include <memory>
#include <unordered_map>
#include <vector>
#include "transport.h"
#include "executors/executors.h"


namespace evm { namespace messaging {

using namespace std;

ExecutorPtr get_executor(ConfigOptsPtr conf, ListenerPtr listener, DispatcherPtr dispatcher);

/* Server for handling messages.
 * Connect a transport to a dispatcher that knows how to process the
 * message using an executor that knows how the app wants to create
 * new tasks.
 */
struct MessageServer {
    MessageServer(TransportPtr transport, DispatcherPtr dispatcher)
        :transport(transport), dispatcher(dispatcher) {}

    void start() {
        auto listener = dispatcher->listen(transport);
        executor = get_executor(transport->conf, listener, dispatcher);
        executor->start();
    }

    void stop() {
        executor->stop();
    }

    void wait() {
        executor->wait();
    }

    TransportPtr transport;
    DispatcherPtr dispatcher;
    ExecutorPtr executor;
};

using MessageServerPtr = shared_ptr<MessageServer>;

}}
